/*
 * Copyright (c) 2024, sakumisu
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include "ff.h"
#include "diskio.h"

#include "drv_sdio.h"

int SDC_disk_initialize(void)
{
    SDIOC_Config();
    if(!SDIOC_IsInited())
    {
        return RES_ERROR;
    }
    
    return RES_OK;
}

int SDC_disk_status(void)
{
    if(!SDIOC_IsInited())
    {
        return RES_ERROR;
    }
    
    return RES_OK;
}

int SDC_disk_read(BYTE *buff, LBA_t sector, UINT count)
{
    SDIOC_ClrTxRxErr();
    
    if((uint32_t)buff % 4 == 0)
    {
        #ifdef CARD_SDC
        if (LL_OK != SD_ReadBlocks_INT(SdCard_GetHandle(), sector, count, (uint8_t*)buff)) 
        #else
        if (LL_OK != MMC_ReadBlocks_DMA(MMC_GetHandle(), sector, count, (uint8_t*)buff)) 
        #endif // CARD_SDC
        {
            return RES_ERROR;
        }
    }
    else
    {
        #ifdef CARD_SDC
        if (LL_OK != SD_ReadBlocks_INT(SdCard_GetHandle(), sector, count, (uint8_t*)buff)) 
        #else
        if (LL_OK != MMC_ReadBlocks_INT(MMC_GetHandle(), sector, count, (uint8_t*)buff)) 
        #endif // CARD_SDC
        {
            return RES_ERROR;
        }
    }
    

    if(xSemaphoreTake(SDIOC_GetSem(), portMAX_DELAY) != pdTRUE)
    {
        return RES_ERROR;
    }
    if(SDIOC_GetTxRxErr())
    {
        return RES_ERROR;
    }
    
    return RES_OK;
}

int SDC_disk_write(const BYTE *buff, LBA_t sector, UINT count)
{
    SDIOC_ClrTxRxErr();
    
    if((uint32_t)buff % 4 == 0)
    {
        #ifdef CARD_SDC
        if (LL_OK != SD_WriteBlocks_INT(SdCard_GetHandle(), sector, count, (uint8_t*)buff)) 
        #else
        if (LL_OK != MMC_WriteBlocks_DMA(MMC_GetHandle(), sector, count, (uint8_t*)buff)) 
        #endif // CARD_SDC
        {
            return RES_ERROR;
        }
    }
    else
    {
        #ifdef CARD_SDC
        if (LL_OK != SD_WriteBlocks_INT(SdCard_GetHandle(), sector, count, (uint8_t*)buff)) 
        #else
        if (LL_OK != MMC_WriteBlocks_INT(MMC_GetHandle(), sector, count, (uint8_t*)buff)) 
        #endif // CARD_SDC
        {
            return RES_ERROR;
        }
    }

    if(xSemaphoreTake(SDIOC_GetSem(), portMAX_DELAY) != pdTRUE)
    {
        return RES_ERROR;
    }
    if(SDIOC_GetTxRxErr())
    {
        return RES_ERROR;
    }
    
    return RES_OK;
}

int SDC_disk_ioctl(BYTE cmd, void *buff)
{
    int result = 0;

    switch (cmd) {
        case CTRL_SYNC:
            result = RES_OK;
            break;

        case GET_SECTOR_SIZE:
            #ifdef CARD_SDC
            *(WORD *)buff = SdCard_GetHandle()->stcSdCardInfo.u32BlockSize;
            #else
            *(WORD *)buff = MMC_GetHandle()->stcMmcCardInfo.u32BlockSize;
            #endif // CARD_SDC
            result = RES_OK;
            break;

        case GET_BLOCK_SIZE:
            *(DWORD *)buff = 1;
            result = RES_OK;
            break;

        case GET_SECTOR_COUNT:
            #ifdef CARD_SDC
            *(DWORD *)buff = SdCard_GetHandle()->stcSdCardInfo.u32BlockNum;
            #else
            *(DWORD *)buff = MMC_GetHandle()->stcMmcCardInfo.u32BlockNum;
            #endif // CARD_SDC
            result = RES_OK;
            break;

        default:
            result = RES_PARERR;
            break;
    }

    return result;
}
